#ifndef ATTRIBUTE_INFO_H
#define  ATTRIBUTE_INFO_H

#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <fstream>
#include <cstdlib>
#include "lexcal.h"

// attribute type
#define  ATTR_DISCRETE     0
#define  ATTR_NUMERIC      1

class attribute_info
{
public:
    //====================================================
    // Construct and Deconstruct
    //====================================================
    attribute_info ()
    {
        _type = ATTR_DISCRETE;
        _id = 0;
        _name = "";
    }

    //build a attribute info from a string
    //typcally,it is from a file.
    attribute_info (string attrinfo)
    {
        //1.AGE numeric
        //1.AGE {a,b,c}
        if (!attrinfo.empty ())
        {
            _id = atoi (cell (attrinfo, '.').c_str ());
            _name = cell (attrinfo, '	');//Tab

            clean (attrinfo);
            if (left_match (attrinfo, "{") && right_match (attrinfo, "}"))
            {
                _type = ATTR_DISCRETE;
                left_sub (attrinfo, "{");
                right_sub (attrinfo, "}");

                while (!attrinfo.empty ())
                {
                    string item = cell (attrinfo, ',');
                    _range.push_back (item);
                }
            }
            else if (attrinfo == "numeric")
            {
                _type = ATTR_NUMERIC;
            }
        }
    }
//copy construct
    attribute_info (const attribute_info& info)
    {
        _id=info._id;
        _type=info._type;
        _name=info._name;
        _range.clear();
        copy(info._range.begin(),info._range.end(),back_inserter(_range));
    }
    //==================================================
    // Print
    //==================================================
    void  print ()
    {
        cout << "ID:    " << _id << endl
        << "NAME:  " << _name << endl
        << "TYPE:  " << _type << endl;
        cout << "RANGE: ";
        copy(_range.begin(),_range.end(),ostream_iterator<string>(cout," "));
        cout <<endl<< endl;
    }

    friend ostream& operator<<(ostream& os, const attribute_info& info)
    {
        os << "id:    " << info._id << endl
           << "name:  " << info._name << endl
           << "type:  " << info._type << endl;
        os << "range: "<<endl;
        copy(info._range.begin(),info._range.end(),ostream_iterator<string>(os," "));
        os <<endl<< endl;
        return os;
    }

    //==================================================
    // utils about the num
    //==================================================
// get id
    int id ()
    {
        return _id;
    }
//set id
    int id (int new_id)
    {
        if (new_id < 0)
        {
            return -1;
        }
        else
        {
            _id = new_id;
            return 0;
        }
    }
//utils of name
//get name
    string name ()
    {
        return _name;
    }
//set name
    string name (string new_name)
    {
        _name = new_name;
        return "";
    }
// utils about the type
// get type
    int type ()
    {
        return _type;
    }
//set type
    int type (int new_type)
    {
        if (new_type != ATTR_DISCRETE && new_type != ATTR_NUMERIC)
        {
            return -1;
        }
        else
        {
            _type = new_type;
            return 0;
        }
    }
//range
    vector<string>& range()
    {
        return _range;
    }


//make vector of attrs
    static vector<attribute_info>* get_all_attr_info(string file)
    {
        vector<attribute_info>* infos = new vector<attribute_info>;
        ifstream sconfig(file.c_str());
        string attr;
        while (getline(sconfig,attr))
        {
            attribute_info i(attr);
            infos->push_back(i);
        }
        return infos;
    }

    //==================================================
    // Member
    //==================================================

    int _id;
    int _type;
    string _name;
    vector < string > _range;	//for discrete
};
#endif
